pinctrl: sunxi: keep a shadow copy of the data register output latches (v6.8) - #365
Open
evgeny-boger wants to merge 1 commit into
Open
pinctrl: sunxi: keep a shadow copy of the data register output latches (v6.8)#365evgeny-boger wants to merge 1 commit into
evgeny-boger wants to merge 1 commit into
Conversation
On Allwinner SoCs, reading a bank's data register returns the pin level, not the output latch, for pins that are muxed as inputs. Writing a GPIO therefore corrupts the output latches of all input-muxed pins in the same bank: the read-modify-write in sunxi_pinctrl_gpio_set() reads back their pin levels and writes those into their latches. This breaks emulated open-drain lines (e.g. a bit-banged I2C bus from i2c-gpio). Such a line is released high by muxing it as input and letting the pull-up raise it, so any concurrent GPIO write in the same bank stores 1 into its latch. Driving the line low afterwards is a non-atomic data-then-mux sequence in sunxi_pinctrl_gpio_direction_output(); if the poisoning write lands between the two steps, the pin actively drives high (push-pull) instead of low. Observed in practice as sporadic SCL/SDA high glitches on a T507 board bit-banging I2C on port E while other PE GPIOs are toggled. The bank spinlock cannot help: the racing write is a perfectly valid whole-register RMW that faithfully writes back what the hardware returned. There are no set/clear registers on this IP to write a single bit atomically. Fix it the same way gpio-mmio handles hardware whose data register read does not return the output latch: keep a shadow copy of each bank's latches, base the read-modify-write on the shadow, and only write the register. The shadow is seeded from the hardware at probe time so pins left in output mode by the bootloader keep their state. Pins that reach output mode through the gpiolib paths write their value (and thereby their shadow bit) before the mux switch in sunxi_pinctrl_gpio_direction_output(); pins muxed to gpio_out directly through a pinmux node bypass that path, so sunxi_pmx_set() refreshes their shadow bit from the latch (readable once the pin is in output mode) to keep them driving their pre-existing level. Fixes: df7b34f ("pinctrl: sunxi: Fix gpio_set behaviour") Cc: stable@vger.kernel.org Signed-off-by: Evgeny Boger <boger@wirenboard.com>
Member
Author
|
Собранный CI-пакет для теста (wb8, arm64): linux-image-wb8_6.8.0-wb160 Установка на контроллер: scp linux-image-wb8_6.8.0-wb160*.deb root@<controller>:/tmp/
ssh root@<controller> "dpkg -i /tmp/linux-image-wb8_6.8.0-wb160*.deb && reboot"Проверено на WB 8.5.1 (T507): загружается ( |
evgeny-boger
marked this pull request as ready for review
July 23, 2026 15:58
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Что происходит; кому и зачем нужно:
На Allwinner чтение регистра данных банка GPIO возвращает уровень пина, а не выходную защёлку, для пинов в режиме входа. Поэтому read-modify-write в
sunxi_pinctrl_gpio_set()портит защёлки всех соседних по банку пинов-входов: обратно записывается считанный уровень пина.Ломает эмулируемый open-drain (i2c-gpio): отпущенная в high линия (вход + подтяжка) получает 1 в защёлку от любой конкурентной записи GPIO в том же банке, и при следующем переводе в low через неатомарную последовательность data→mux в
sunxi_pinctrl_gpio_direction_output()пин может активно выдать push-pull high вместо low. Наблюдалось на WB 8.5.1 (T507): спорадические выбросы SCL/SDA в high на битбанг-шине ATECC/RTC (порт E) при переключении других PE-GPIO (A1 OUT, W2 UP и т.п.).Исправление: теневая копия защёлок по банкам (по образцу gpio-mmio), RMW ведётся по тени, регистр только пишется. Тень сеется из железа на probe; пины, замуксенные в gpio_out напрямую через pinmux, обновляют свой бит тени в
sunxi_pmx_set().Патч предназначен для отправки в mainline (Fixes: df7b34f, Cc: stable).
Что поменялось для пользователей:
Исчезают спорадические глитчи на программных (bitbang) I2C-шинах и вообще любых эмулируемых open-drain линиях на sunxi при активности других GPIO того же банка. Прочее поведение GPIO не меняется.
Как проверял/а:
scripts/checkpatch.plна итоговом патче: 0 errors, 0 warnings (обе ветки).sunxi_pmx_set().